package com.example.webflux;

import com.example.webflux.bean.User;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.util.*;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamProgram {

    @Test
    public void randomStream() {
        Runnable runnable = () -> new Random(100)
                .ints(20, 80)
                .distinct()
                .limit(10)
                .sorted()
                .forEach(System.out::println);
        runnable.run();
    }

    @Test
    public void streamTest() {
        Stream.of(new User(1).getUserId(), new User(2).getUserId(), new User(3).getUserId()).forEach(System.out::println);
        Stream.of("a", "b", "c", "d", "e", "f").forEach(System.out::println);
        Stream.of(3.14159, 2.718, 1.618).forEach(System.out::println);
        Consumer callbackHandler = System.out::println;
        callbackHandler.accept("==================List====================");
        List<User> list = Arrays.asList(new User(1), new User(2), new User(3));
        list.stream().filter(u -> u.getUserId() >= 2).map(user -> user.getUserId()).forEach(System.out::println);
        Set<String> set = new HashSet<>(Arrays.asList("a", "b", "c", "d", "e", "f"));
        set.stream().forEach(System.out::println);
        callbackHandler.accept("=====================Random===========================");
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
        callbackHandler.accept("=====================Itretor=======================");
        Stream.iterate(0, n -> n + 1).limit(10).forEach(System.out::println);
        callbackHandler.accept("===================Array=====================");
        int[][] ints = {{2, 5, 8}, {3, 6, 9}, {4, 7, 8}};
        Arrays.stream(new double[]{3.14159, 2.718, 1.618}).forEach(System.out::println);
        callbackHandler.accept("------------------------------------------");
        Arrays.stream(ints).forEach(i -> {
            Arrays.stream(i).forEach(n -> System.out.format(Locale.US, "%d ", n));
            System.out.println();
        });
        callbackHandler.accept("------------------------------------------");
        Arrays.stream(new long[]{11, 22, 44, 66}).forEach(n->{
            System.out.println(n);
        });
        callbackHandler.accept("------------------------------------------");
        // 选择一个子域
        Arrays.stream(new int[]{1, 3, 5, 7, 15, 28, 37}, 3, 6).forEach(System.out::println);
        callbackHandler.accept("----------Pattern----------");
        Pattern.compile("[.,?]+").splitAsStream("a,b,c,d,e").forEach(System.out::println);
        callbackHandler.accept("-----------Function-----------------------------");
        Arrays.stream(new String[] {"12", "23", "34"}).map(s -> "[" + s + "]")
                .forEach(System.out::println);
        callbackHandler.accept("----------------------FlatMap------------------------------------");
        Stream.of(1, 2, 3).flatMap(i -> Stream.of("hello" + i)).forEach(System.out::println);
        callbackHandler.accept("====================ArrayList-Sum=====================================");
        int i = Arrays.stream(new int[]{1, 3, 5, 7, 15, 28, 37}).filter(n -> n % 2 != 0).reduce(Integer::sum).orElse(0);
        System.out.println(i);
    }
    @Test
  public void userStreamTest(){
        User user1 = User.builder()
                .userId(1)
                .name("tom")
                .age(21)
                .desc("desc")
                .build();

        User user2 = User.builder()
                .userId(2)
                .name("jack")
                .age(10)
                .desc("desc")
                .build();

        User user3 = User.builder()
                .userId(3)
                .name("mina")
                .age(23)
                .desc("desc")
                .build();

        User user4 = User.builder()
                .userId(4)
                .name("jerry")
                .age(27)
                .desc("desc")
                .build();

        List<User> userList = Arrays.asList(user1, user2, user3, user4);

        userList.stream().filter(new User()::grap)
                .map(new User()::userGrowth)
                .map(User::getUserId)
                .forEach(System.out::println);
    }

    @org.junit.Test
    public void rangeTest(){
        Flux.range(1, 1000)
                .onBackpressureBuffer(100, e -> System.out.println("Buffer full"))
                .subscribe(System.out::println);
    }

    @org.junit.Test
    public void delayTest(){
        Mono.delay(Duration.ofSeconds(1))
                .flatMap(delay -> Mono.just("Hello"))
                .doOnTerminate(() -> System.out.println("Process completed"))
                .subscribe(System.out::println);
    }


    @Test
    public void testRecator() {
        Flux.just(1, 2, 3, 4, 5).flatMap(INumber::asynNumber).subscribe(System.out::println);
    }

    @Test
    public void testStream() {
        int num1[] = {2, 3, 4};
        int num2[] = {8, 9, 7};

        Arrays.asList(num1, num2).stream().flatMap(v->{
            Arrays.stream(v).forEach(l->l+=2);
            return Stream.of(v);
        }).forEach(v2->Arrays.stream(v2).forEach(System.out::println));
    }

    @Test
    public void mergeArray(){
        // 创建两个数组
        Integer[] array1 = {1, 2, 3};
        Integer[] array2 = {4, 5, 6};

        // 创建Flux流
        Flux<Integer> flux1 = Flux.fromArray(array1);
        Flux<Integer> flux2 = Flux.fromArray(array2);

        // 合并两个数组并计算和
        Flux<Integer> mergedFlux = Flux.merge(flux1, flux2)
                .map(value -> value + 1); // 假设我们对每个值进行加1操作

        // 订阅并输出结果
        mergedFlux.subscribe(System.out::println);
    }

    @Test
    public void testCal(){
        int num =100;
        System.out.println(sumCal(num));
    }

    public int sumCal(int n){
        return n==0?0:n+sumCal(n-1);
    }
}

@FunctionalInterface
interface INumber {
    public Flux<Integer> asyn(Integer n);

    public static Flux<Integer> asynNumber(Integer n) {
        n = n % 2 == 0 ? n + 2 : n * 2;
        return Flux.just(n);
    }
}
